"""
FastAPI应用主文件
"""

from fastapi import FastAPI, HTTPException, Depends, Request
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import uvicorn

from .config import config
from .logger import logger
from .storage import data_manager
from .models import ErrorResponse


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动时的初始化
    logger.info("Starting Model Subscription System...")

    # 确保数据目录存在
    storage_config = config.get_storage_config()
    data_dir = storage_config.get('data_dir', 'data')
    import os
    os.makedirs(data_dir, exist_ok=True)
    os.makedirs('logs', exist_ok=True)

    # 启动各种服务
    from .services.subscription_service import subscription_service
    from .services.discovery_service import discovery_service
    from .services.notification_service import notification_service
    from .services.event_dispatcher import event_dispatcher

    await event_dispatcher.start()
    await notification_service.start()
    await subscription_service.start()
    await discovery_service.start()

    logger.info("System initialized successfully")

    yield

    # 关闭时的清理
    logger.info("Shutting down Model Subscription System...")

    # 停止各种服务
    await discovery_service.stop()
    await subscription_service.stop()
    await notification_service.stop()
    await event_dispatcher.stop()


def create_app() -> FastAPI:
    """创建FastAPI应用"""
    api_config = config.get('api', {})
    
    app = FastAPI(
        title=api_config.get('title', '模型订阅与状态下发系统'),
        description=api_config.get('description', 'YOLO推理服务的模型订阅和状态管理API'),
        version=api_config.get('version', 'v1'),
        lifespan=lifespan,
        docs_url=None,  # 禁用默认docs
        redoc_url=None,  # 禁用默认redoc
        openapi_url="/openapi.json"
    )
    
    # 设置中间件
    from .middleware import setup_middleware
    setup_middleware(app)
    
    # 注册路由
    from .routes import models, subscriptions, servers, health, websocket, notifications, web_compat, batch, admin, clients, model_status, model_dispatch

    api_prefix = f"/api/{api_config.get('version', 'v1')}"

    app.include_router(health.router, prefix=api_prefix, tags=["健康检查"])
    app.include_router(models.router, prefix=api_prefix, tags=["模型管理"])
    app.include_router(subscriptions.router, prefix=api_prefix, tags=["订阅管理"])
    app.include_router(servers.router, prefix=api_prefix, tags=["服务器管理"])
    app.include_router(clients.router, prefix=api_prefix, tags=["客户端管理"])
    app.include_router(model_status.router, prefix=api_prefix, tags=["模型状态汇报"])
    app.include_router(notifications.router, prefix=api_prefix, tags=["通知管理"])
    app.include_router(batch.router, prefix=api_prefix, tags=["批量操作"])
    app.include_router(admin.router, prefix=api_prefix, tags=["系统管理"])
    app.include_router(model_dispatch.router, prefix=api_prefix, tags=["模型分发"])
    app.include_router(websocket.router, prefix=api_prefix, tags=["WebSocket通信"])

    # Web客户端兼容路由（无前缀）
    app.include_router(web_compat.router, tags=["Web客户端兼容"])

    # 管理界面路由（单独添加，无API前缀）
    @app.get("/admin/")
    async def admin_interface():
        """返回管理界面HTML页面"""
        from fastapi.responses import FileResponse
        import os
        admin_html_path = os.path.join("static", "admin", "index.html")
        if os.path.exists(admin_html_path):
            return FileResponse(admin_html_path, media_type="text/html")
        else:
            raise HTTPException(status_code=404, detail="管理界面页面未找到")

    # 挂载静态文件服务
    app.mount("/static", StaticFiles(directory="static"), name="static")

    # 自定义文档路由（使用国内CDN）
    @app.get("/docs", include_in_schema=False)
    async def custom_swagger_ui_html():
        return HTMLResponse("""
<!DOCTYPE html>
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/swagger-ui/5.10.3/swagger-ui.css">
    <link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
    <title>模型订阅与状态下发系统 - API文档</title>
</head>
<body>
    <div id="swagger-ui">
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/swagger-ui/5.10.3/swagger-ui-bundle.min.js"></script>
    <script>
    const ui = SwaggerUIBundle({
        url: '/openapi.json',
        dom_id: '#swagger-ui',
        layout: 'BaseLayout',
        deepLinking: true,
        showExtensions: true,
        showCommonExtensions: true,
        presets: [
            SwaggerUIBundle.presets.apis,
            SwaggerUIBundle.SwaggerUIStandalonePreset
        ],
    })
    </script>
</body>
</html>
        """)

    @app.get("/redoc", include_in_schema=False)
    async def redoc_html():
        return HTMLResponse("""
<!DOCTYPE html>
<html>
<head>
    <title>模型订阅与状态下发系统 - ReDoc</title>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcdn.net/ajax/libs/redoc/2.1.3/redoc.standalone.css" rel="stylesheet">
</head>
<body>
    <redoc spec-url='/openapi.json'></redoc>
    <script src="https://cdn.bootcdn.net/ajax/libs/redoc/2.1.3/redoc.standalone.js"></script>
</body>
</html>
        """)

    # 全局异常处理
    @app.exception_handler(Exception)
    async def global_exception_handler(request, exc):
        logger.error(f"Unhandled exception: {exc}", exc_info=True)
        return JSONResponse(
            status_code=500,
            content=ErrorResponse(
                message="Internal server error",
                error_code="INTERNAL_ERROR"
            ).model_dump()
        )

    @app.exception_handler(HTTPException)
    async def http_exception_handler(request, exc):
        return JSONResponse(
            status_code=exc.status_code,
            content=ErrorResponse(
                message=exc.detail,
                error_code=f"HTTP_{exc.status_code}"
            ).model_dump()
        )
    
    return app


# 创建应用实例
app = create_app()


def run_server():
    """运行服务器"""
    server_config = config.get_server_config()
    
    uvicorn.run(
        "src.app:app",
        host=server_config.get('host', '0.0.0.0'),
        port=server_config.get('port', 7880),
        reload=server_config.get('reload', False),
        log_level=config.get('logging.level', 'info').lower()
    )


if __name__ == "__main__":
    run_server()
